﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using MathematicallySafe.HeadCounter.Data.Common;
using MathematicallySafe.Armourer;
using MathematicallySafe.HeadCounter.Commands;
using MathematicallySafe.HeadCounter.Data;
using MathematicallySafe.HeadCounter.Data.Models;
using MathematicallySafe.HeadCounter.Services;
using StructureMap;

namespace MathematicallySafe.HeadCounter.ViewModels
{
    public class RaidersViewModel: ViewModelBase
    {
        private static readonly IHeadCounterService HeadCounterService = ObjectFactory.GetInstance<IHeadCounterService>();
        private static readonly IArmouryService ArmouryService = ArmouryServiceFactory.Instance.GetArmouryService();

        private readonly ICalculationService _calculator = ObjectFactory.GetInstance<ICalculationService>();

        private ObservableCollection<RaiderDetailedViewModel> _raiders;

        private SortDescription ByNameAscending = new SortDescription("Name", ListSortDirection.Ascending);

        private DelegateCommand _processDataCommand;
        private DelegateCommand _exportDataCommand;
        private DelegateCommand _downloadAllRaidersCommand;

        public ListCollectionView Raiders { get; private set; }

        public RaidersViewModel()
        {
            LoadRaiders();
        }

        private void LoadRaiders()
        {
            _raiders = new ObservableCollection<RaiderDetailedViewModel>();
            HeadCounterService.Guild.ActiveRaidersByMain.ForEach(r => _raiders.Add(new RaiderDetailedViewModel(r)));

            Raiders = new ListCollectionView(_raiders);
            Raiders.SortDescriptions.Add(ByNameAscending);
        }

        public static string ShortPeriodAttendanceLabel
        {
            get { return string.Format("{0}WkAtt%", HeadCounterService.Options.ShortPeriodLength); }
        }

        public static string LongPeriodAttendanceLabel
        {
            get { return string.Format("{0}WkAtt%", HeadCounterService.Options.LongPeriodLength); }
        }

        #region Commands

        public ICommand ProcessDataCommand
        {
            get
            {
                if (_processDataCommand == null)
                {
                    _processDataCommand = new DelegateCommand(ProcessData);
                }

                return _processDataCommand;
            }
        }

        private void ProcessData()
        {
            var calculator = ObjectFactory.GetInstance<ICalculationService>();
            calculator.Process();

            ObjectFactory.GetInstance<IHeadCounterService>().Save();
        }

        public ICommand ExportDataCommand
        {
            get
            {
                if (_exportDataCommand == null)
                {
                    _exportDataCommand = new DelegateCommand(exportData);
                }

                return _exportDataCommand;
            }
        }

        private void exportData()
        {
            var forumPosterService = ObjectFactory.GetInstance<IForumPostingService>();

            var raiders = from r in HeadCounterService.Guild.ActiveRaiders
                          orderby r.Class, r.ShortPeriodAttendance descending
                          select r;

            forumPosterService.PostGuildSummary(raiders);
        }

        public ICommand DownloadAllRaidersCommand
        {
            get
            {
                if (_downloadAllRaidersCommand == null)
                {
                    _downloadAllRaidersCommand = new DelegateCommand(DownloadAllRaiders);
                }

                return _downloadAllRaidersCommand;
            }
        }

        private void DownloadAllRaiders()
        {
            if (
                MessageBox.Show("Do you really want to download all raiders from the armoury?", "Confirm Download",
                                MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                var options = HeadCounterService.Options;
                var guild = HeadCounterService.Guild;

                guild.ActiveRaidersByMain.ForEach(r => ArmouryService.EnqueueGetCharacter(options.Region, options.Realm, r.Name));
                ArmouryService.RunArmouryServiceAsync();
            }
        }

        #endregion

        #region Events

        protected override void SubscribeEvents()
        {
            HeadCounterService.Guild.RaiderAdded += GuildRaiderAdded;
            HeadCounterService.Guild.RaiderRemoved += GuildRaiderRemoved;

            _calculator.Processed += DataUpdated; 
        }

        protected override void UnsubscribeEvents()
        {
            HeadCounterService.Guild.RaiderAdded -= GuildRaiderAdded;
            HeadCounterService.Guild.RaiderRemoved -= GuildRaiderRemoved;
            _calculator.Processed -= DataUpdated; 
        }

        void GuildRaiderAdded(object sender, RosterChangedEventArgs e)
        {
            var raiderViewModel = new RaiderDetailedViewModel(e.Raider);
            raiderViewModel.Initialise();

            _raiders.Add(raiderViewModel);
        }

        void GuildRaiderRemoved(object sender, RosterChangedEventArgs e)
        {
            // todo if this is ever used, prob won't work becuase of name != identity issues.
            var raiderViewModel = _raiders.FirstOrDefault(r => r.Name == e.Raider.Identity);

            if (raiderViewModel != null)
            {
                _raiders.Remove(raiderViewModel);
                raiderViewModel.Dispose();
            }
        }

        private void DataUpdated()
        {
            OnPropertyChanged("Raiders");
        }

        #endregion Events
    }
}
